﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using mBook.ViewModels;
using Windows.Storage;
using mBook.Utils;
using mBook.Models;
using System.Threading.Tasks;
using Windows.Data.Xml.Dom;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Collections.ObjectModel;
using mBook.UserControls;
using Windows.UI;
using Windows.UI.Xaml.Shapes;

// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237

namespace mBook.Views
{

    /// <summary>
    /// A basic page that provides characteristics common to most applications.
    /// </summary>
    public sealed partial class EpubViewerPage : mBook.Common.LayoutAwarePage
    {
        GroupedItemsPage mainPage = null;
        WebView previousSelectWebView;

        private EbookViewModel ebook;
        int idx_right = 0;
        int idx_current = 0;
        int idx_left = 0;

        bool isLoadFinish = false;

        ObservableCollection<PageViewModel> pages = new ObservableCollection<PageViewModel>();

        public EpubViewerPage()
        {
            this.InitializeComponent();
            
        }

        /// <summary>
        /// Populates the page with content passed during navigation.  Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="navigationParameter">The parameter value passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
        /// </param>
        /// <param name="pageState">A dictionary of state preserved by this page during an earlier
        /// session.  This will be null the first time a page is visited.</param>
        protected override async void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            Dictionary<String, object> dict = (Dictionary<String, object>)navigationParameter;
            mainPage = (GroupedItemsPage)dict["MainPage"];

            var item = ManagerDataViewModel.GetItem((String)dict["itemID"]);
            //flipView.DataContext = pages;

            //this.DefaultViewModel["Group"] = item.Group;
            //this.DefaultViewModel["Items"] = item.Group.Items;
            ebook = item;

            pageTitle.Text = ebook.Title;
            statusDownloading.DataContext = ManagerDataViewModel.GetStatusDownload();

            Init();
        }

        private async void Init()
        {
            await parseInfoEbook();

            App.EbookReading = ebook;

            //ebook hasn't been read 
            if (ebook.EpubEbook.CurrentPageReading == "")
            {

                ReadEpub(page1, idx_right);

                flipView.SelectedItem = page1;

                if (ebook.EpubEbook.Spine.Count > 1)
                {
                    idx_right = 1;
                    ReadEpub(page2, idx_right);
                }

                if (ebook.EpubEbook.Spine.Count > 2)
                {
                    idx_right = 2;
                    ReadEpub(page3, idx_right);
                }

                
                
            }
            else
            {
                jumpToPage(ebook.EpubEbook.CurrentPageReading);
            }

            previousSelectWebView = page1;
            isLoadFinish = true;
            //ReadEpub(testWebView, 0);

        }

        #region read and parse ebook

        private void addTableContent()
        {
            String currentHref = ebook.EpubEbook.Items[ebook.EpubEbook.Spine[idx_current]];

            foreach (ItemTableContent item in ebook.EpubEbook.TableContents)
            {
                uc_itemTableContent uc_item = new uc_itemTableContent();
                uc_item.Margin = new Thickness(0);
                uc_item.Item = item;
                uc_item.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Right;

                if (item.Href == currentHref)
                {
                    uc_item.setSelectedStatus();
                }

                ltv_tableContent.Items.Add(uc_item);

                if (item.ListChildItems != null)
                {
                    foreach (ItemTableContent childItem in item.ListChildItems)
                    {
                        SmallItemTableContent small_item = new SmallItemTableContent();
                        small_item.Margin = new Thickness(25, 0, 0, 0);
                        small_item.Item = childItem;
                        small_item.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Right;

                        if (item.Href == currentHref)
                        {
                            small_item.setSelectedStatus();
                        }

                        ltv_tableContent.Items.Add(small_item);
                    }
                }
            }
        }

        public void addBookmark()
        {
            foreach (ItemTableContent item in ebook.EpubEbook.TableContents)
            {
                if (item.IsBookmark)
                {
                    uc_itemTableContent uc_item = new uc_itemTableContent();
                    uc_item.Margin = new Thickness(0);
                    uc_item.Item = item;
                    uc_item.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Right;

                    ltv_tableContent.Items.Add(uc_item);
                }
            }
        }

        public async Task parseInfoEbook()
        {
            ShowWaitingDialog();
            try
            {
                StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.CreateFolderAsync(Constants.FOLDER_DATA_EXTRACT, CreationCollisionOption.OpenIfExists);
                StorageFile fileConfig = await folderEbook.GetFileAsync(ebook.EBook.Name + "." + ebook.EBook.FileType + "\\config");
                EpubEbook epub = await EpubViewModel.ParseFileToEbook(fileConfig) as EpubEbook;
                ebook.EpubEbook = epub;

                //addTableContent();
            }catch
            {
                ////this is first read ebook
            }


            if (ebook.EpubEbook == null)
            {
                StorageFile file;
                try
                {
                    file = await ApplicationData.Current.LocalFolder.GetFileAsync(ebook.EBook.FilePath);
                }
                catch (Exception e)
                {
                    App.ShowMessage("This file is deleted");
                    return;
                }

                if (file != null)
                {
                    

                    try
                    {
                        await Utility.UnZipFile(file);

                        EpubEbook epub = await AnalyzeDocument(file.DisplayName);

                        if (ebook != null)
                        {
                             

                            // Add to Items
                            //StorageFile imageCoverFile = null;
                            //if (ebook.ImageCover != null && ebook.ImageCover != "")
                            //    imageCoverFile = await ApplicationData.Current.LocalFolder.GetFileAsync(rootFolder + "\\" + ebook.ImageCover.Replace("/", "\\"));

                            ebook.EpubEbook = epub;

                            readAndSaveInfoEbook();
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }

                    
                }
                else
                {
                    App.ShowMessage("Cannot open this file.");
                }
            }

            HideWaitingDialog();
        }

        private async void readAndSaveInfoEbook()
        {
            await readTableContent();
            //addTableContent();

            EpubViewModel.CreateJsonEbook(ebook.EpubEbook);
        }

        private async Task<EpubEbook> AnalyzeDocument(string filename)
        {
            StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.CreateFolderAsync(Constants.FOLDER_DATA_EXTRACT, CreationCollisionOption.OpenIfExists);
            StorageFile file = await folderEbook.GetFileAsync(filename + "\\META-INF\\container.xml");

            XmlDocument doc = await XmlDocument.LoadFromFileAsync(file);
            try
            {
                string pathContainer = GetContainerPath(doc.ChildNodes);
                string rootFolder = filename + "\\" + pathContainer;
                if (pathContainer.Contains("/"))
                    rootFolder = filename + "\\" + pathContainer.Substring(0, pathContainer.LastIndexOf("/"));

                StorageFile containerFile = await folderEbook.GetFileAsync(filename + "\\" + pathContainer.Replace("/", "\\"));
                XmlDocument containerDoc = await XmlDocument.LoadFromFileAsync(containerFile);

                EpubEbook ebook = EpubViewModel.ParseToEbook(rootFolder, filename, containerDoc);

                return ebook;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return null;
        }

        private string GetContainerPath(XmlNodeList nodes)
        {
            string path = "";
            foreach (var element in nodes)
            {
                if (element.NodeType == NodeType.ElementNode)
                {
                    if (element.NodeName == "rootfile")
                    {
                        path = element.Attributes[0].NodeValue as string;
                    }
                    else if (element.HasChildNodes())
                    {
                        path = GetContainerPath(element.ChildNodes);
                    }
                }
            }

            return path;
        }

        

        private async void ReadEpub(WebView webView, int indexPage)
        {
            if (indexPage < ebook.EpubEbook.Spine.Count)
            {
                try
                {
                    string path = ebook.EpubEbook.Items[ebook.EpubEbook.Spine[indexPage]];
                    if (path.Contains("/"))
                        path = path.Replace("/", "\\");

                    StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.GetFolderAsync(Constants.FOLDER_DATA_EXTRACT);
                    StorageFile file = await folderEbook.GetFileAsync(ebook.EpubEbook.RootFolder + "\\" + path);

                    //TODO: decrypt
                    string html = await Windows.Storage.PathIO.ReadTextAsync(file.Path);

                    //string html = await AESUtils.DecryptEpubToString(file, Constants.PASS_PHRASE);
                    //html = DecryptImages(html); 

                    html = await ModifyHTML(html, ebook.EBook.Password);

                    webView.NavigateToString(html);

                    //webView.Navigate(new Uri("ms-appx-web:///Assets/1/OPS/s002-Part-001.xhtml"));
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
        }



        private async void ReadEpub(WebView webView, String path)
        {
            
            try
            {
                if (path.Contains("/"))
                    path = path.Replace("/", "\\");

                StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.GetFolderAsync(Constants.FOLDER_DATA_EXTRACT);
                StorageFile file = await folderEbook.GetFileAsync(ebook.EpubEbook.RootFolder + "\\" + path);

                //string html = await Windows.Storage.PathIO.ReadTextAsync(file.Path);

                string html = await AESUtils.DecryptEpubToString(file, Constants.PASS_PHRASE);
                //html = DecryptImages(html); 

                html = await ModifyHTML(html, ebook.EBook.Password);

                webView.NavigateToString(html);

                //webView.Navigate(new Uri("ms-appx-web:///Assets/1/OPS/s002-Part-001.xhtml"));
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            
        }

        private async Task readTableContent()
        {
            string path;
            try
            {
                path = ebook.EpubEbook.Items["toc"];
            }
            catch
            {
                //epub dont have table content
                return;
            }
            if (path.Contains("/"))
                path = path.Replace("/", "\\");

            StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.GetFolderAsync(Constants.FOLDER_DATA_EXTRACT);
            StorageFile file = await folderEbook.GetFileAsync(ebook.EpubEbook.RootFolder + "\\" + path);
            try
            {
                //TODO: decrypt
                String html = await Windows.Storage.PathIO.ReadTextAsync(file.Path);
                //String html = await AESUtils.DecryptEpubToString(file, Constants.PASS_PHRASE);
                html.Replace("<!DOCTYPE html>", "");

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(html);

                //XmlDocument containerDoc = await XmlDocument.LoadFromFileAsync(file);

                ebook.EpubEbook.TableContents = await EpubViewModel.parseTableContent(doc);
            }
            catch (Exception exe)
            {
                
                
            }
           
            //html.Split(
        }

        #endregion

        #region modify html


        private async Task<string> ModifyHTML(string html, String password)
        {
            html = await ImportCss(html);
            //html = await AddCss(html);

            html = await addJavaScript(html);

            html = await AddImages(html, password);

            html = await addVideo(html);

            return html;
        }

        private async Task<string> ImportCss(string html)
        {
            string cssText = "";
            StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.GetFolderAsync(Constants.FOLDER_DATA_EXTRACT);
            var folders = await folderEbook.GetFolderAsync(ebook.EpubEbook.RootFolder);

            var innerFolders = await folders.GetFoldersAsync();

            foreach (var folder in innerFolders)
            {
                if (folder.Name == "css")
                {
                    var files = await folder.GetFilesAsync();
                    foreach (var file in files)
                    {
                        StorageFile cssFile = await folder.GetFileAsync(file.Name);

                        var css = await Windows.Storage.PathIO.ReadTextAsync(cssFile.Path);

                        cssText += css;
                    }
                    break;
                }
            }

            html = html.Replace("<head>", "<head><style type=\"text/css\">" + cssText + "</style>");

            return html;
        }

        private async Task<string> AddCss(string html)
        {
            Regex regCss = new Regex("<link.+?href=[\"'](.+?)[\"'].+?>");
            MatchCollection matchCss = regCss.Matches(html);
            //string cssText = "";
            string absolutePath = "";
            foreach (Match m in matchCss)
            {
                Regex reg = new Regex("href=[\"'](.+?)[\"']");
                Match matchReg = reg.Match(m.Value);

                string strCss = matchReg.Value.Substring(matchReg.Value.IndexOf("\"") + 1, matchReg.Value.LastIndexOf("\"") - matchReg.Value.IndexOf("\"") - 1);
                string linkCss = strCss.Replace("/", "\\");

                StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.GetFolderAsync(Constants.FOLDER_DATA_EXTRACT);
                StorageFile cssFile = await folderEbook.GetFileAsync(ebook.EpubEbook.RootFolder + "\\" + linkCss);

                absolutePath = cssFile.Path;
                //var css = await Windows.Storage.PathIO.ReadTextAsync(cssFile.Path);

                //cssText += css;
                html = html.Replace(strCss, absolutePath);
            }

            

            return html;
        }

        private async Task<String> addJavaScript(String html)
        {
            Regex regCss = new Regex("<script.+?src=[\"'](.+?)[\"'].+?>");
            MatchCollection matchCss = regCss.Matches(html);
            //string cssText = "";
            
            foreach (Match m in matchCss)
            {
                Regex reg = new Regex("src=[\"'](.+?)[\"']");
                Match matchReg = reg.Match(m.Value);

                string strJs = matchReg.Value.Substring(matchReg.Value.IndexOf("\"") + 1, matchReg.Value.LastIndexOf("\"") - matchReg.Value.IndexOf("\"") - 1);
                string linkJs = strJs.Replace("/", "\\");

                StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.GetFolderAsync(Constants.FOLDER_DATA_EXTRACT);
                StorageFile cssFile = await folderEbook.GetFileAsync(ebook.EpubEbook.RootFolder + "\\" + linkJs);

                
                String js = await Windows.Storage.PathIO.ReadTextAsync(cssFile.Path);

                //html = html.Replace(matchReg.Value,"");
                html = html.Replace(m.Value, "<script type=\"text/javascript\" >" + js + "</script>");
                
                
            }
            return html;
        }



        private async Task<string> AddImages(string html, string password)
        {

            Regex reg = new Regex("<img.+?src=[\"'](.+?)[\"']\\s.+?>", RegexOptions.IgnoreCase);
            MatchCollection collection = reg.Matches(html);
            foreach (Match match in collection)
            {
                string imgInnerHtml = match.Value;

                Regex regImg = new Regex("src=[\"'](.+?)[\"']");
                Match matchReg = regImg.Match(imgInnerHtml);

                string matchRegValue = matchReg.Value;
                if (matchRegValue.Contains("../"))
                    matchRegValue = matchRegValue.Replace("../", "");

                string img = "", sep = "";
                if (matchRegValue.Contains("'"))
                {
                    img = matchRegValue.Substring(matchRegValue.IndexOf("'") + 1, matchRegValue.LastIndexOf("'") - matchRegValue.IndexOf("'") - 1);
                    sep = "'";
                }
                else
                {
                    img = matchRegValue.Substring(matchRegValue.IndexOf("\"") + 1, matchRegValue.LastIndexOf("\"") - matchRegValue.IndexOf("\"") - 1);
                    sep = "\"";
                }

                string image = img.Replace("/", "\\");
                StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.GetFolderAsync(Constants.FOLDER_DATA_EXTRACT);
                StorageFile imageFile = await folderEbook.GetFileAsync(ebook.EpubEbook.RootFolder + "\\" + image);

                // byte[] byteImage = await AESUtils.DecryptEpubToBytes(imageFile.Path, password);

                //TODO: decrypt
                string base64 = await Utility.ConvertBase64(imageFile);
                //string base64 = await AESUtils.DecryptEpubToString(imageFile, password);

                string ext = img.Substring(img.IndexOf(".") + 1, img.Length - img.IndexOf(".") - 1);

                html = html.Replace(matchReg.Value, "src=" + sep + "data:image/" + ext + ";base64," + base64 + sep);
            
            }

            return html;
        }

        private async Task<string> addVideo(string html)
        {
            Regex reg = new Regex("<source.+?src=[\"'](.+?)[\"']\\s.+?>");
            MatchCollection collection = reg.Matches(html);
            foreach (Match match in collection)
            {
                string imgInnerHtml = match.Value;

                Regex regImg = new Regex("src=[\"'](.+?)[\"']");
                Match matchReg = regImg.Match(imgInnerHtml);

                string matchRegValue = matchReg.Value;
                if (matchRegValue.Contains("../"))
                    matchRegValue = matchRegValue.Replace("../", "");

                string img = "", sep = "";
                if (matchRegValue.Contains("'"))
                {
                    img = matchRegValue.Substring(matchRegValue.IndexOf("'") + 1, matchRegValue.LastIndexOf("'") - matchRegValue.IndexOf("'") - 1);
                    sep = "'";
                }
                else
                {
                    img = matchRegValue.Substring(matchRegValue.IndexOf("\"") + 1, matchRegValue.LastIndexOf("\"") - matchRegValue.IndexOf("\"") - 1);
                    sep = "\"";
                }

                string image = img.Replace("/", "\\");
                StorageFolder folderEbook = await ApplicationData.Current.LocalFolder.GetFolderAsync(Constants.FOLDER_DATA_EXTRACT);
                StorageFile imageFile = await folderEbook.GetFileAsync(ebook.EpubEbook.RootFolder + "\\" + image);

                //string base64 = await Utilities.Utils.ConvertBase64(imageFile);

                //string ext = img.Substring(img.IndexOf(".") + 1, img.Length - img.IndexOf(".") - 1);

                //html = html.Replace(matchReg.Value, "src=" + sep + "data:image/" + ext + ";base64," + base64 + sep);

                html = html.Replace(matchReg.Value, "src=\"" + imageFile.Path + "\"");
            }

            return html;
        }

        #endregion

        private ItemTableContent findItemByLink(String link)
        {

            foreach (ItemTableContent item in ebook.EpubEbook.TableContents)
            {
                if (item.Href == link)
                    return item;
                if (item.ListChildItems != null)
                {
                    foreach (ItemTableContent childItem in item.ListChildItems)
                    {
                        if (item.Href == link)
                            return item;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// Preserves state associated with this page in case the application is suspended or the
        /// page is discarded from the navigation cache.  Values must conform to the serialization
        /// requirements of <see cref="SuspensionManager.SessionState"/>.
        /// </summary>
        /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
        protected override void SaveState(Dictionary<String, Object> pageState)
        {

        }

        private void ShowWaitingDialog()
        {
            prgBar.Visibility = Windows.UI.Xaml.Visibility.Visible;
        }

        private void HideWaitingDialog()
        {     
            prgBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        }

        private void SwitchWebView(WebView webView, Rectangle webViewBrushRect,  bool back)
        {
            if (!back)
            {
                WebViewBrush brush = new WebViewBrush();
                brush.SourceName = webView.Name;
                brush.Redraw();

                webViewBrushRect.Visibility = Windows.UI.Xaml.Visibility.Visible;
                webViewBrushRect.Fill = brush;
                //webViewBrushRect.UpdateLayout();
                //webView.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                flipView.Visibility = Windows.UI.Xaml.Visibility.Collapsed;

            }
            else
            {
                //webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
                flipView.Visibility = Windows.UI.Xaml.Visibility.Visible;
                webViewBrushRect.Fill = new SolidColorBrush(Colors.Transparent);
            }
        }

        private void switchFakeWebView(WebView webView, Rectangle webViewBrushRect, bool back)
        {
            if (!back)
            {
                WebViewBrush brush = new WebViewBrush();
                brush.SourceName = webView.Name;
                brush.Redraw();

                webViewBrushRect.Visibility = Windows.UI.Xaml.Visibility.Visible;
                webViewBrushRect.Fill = brush;
                //webViewBrushRect.UpdateLayout();
                webView.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
            }
            else
            {
                webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
                webViewBrushRect.Fill = new SolidColorBrush(Colors.Transparent);
            }
        }

        private void flipView_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
        {

            //first init flipview
            if (isLoadFinish && flipView.SelectedItem != null)
            {
             
                
                int pre_idx = flipView.Items.IndexOf(previousSelectWebView);
                int cur_idx = flipView.SelectedIndex;

                if (cur_idx != 1)
                {
                    //move left --> move to next chapter
                    if (pre_idx < cur_idx)
                    {
                        if (idx_right < ebook.EpubEbook.Spine.Count - 1)
                        {
                            ++idx_right;
                            ++idx_left;
                            idx_current = idx_left + 1;

                            //because move to next page so current page not element 0
                            WebView leftPage = getLeftPage();
                            addRightPage(leftPage);
                            ReadEpub(leftPage, idx_right);
                        }
                    }
                    else //move right --> move to previous chapter
                    {
                        if (idx_left > 0)
                        {
                            idx_left--;
                            idx_right--;
                            idx_current = idx_left + 1;

                            WebView rightPage;
                            if (ebook.EpubEbook.Spine.Count >= 2)
                                rightPage = flipView.Items.ElementAt(2) as WebView;
                            else if (ebook.EpubEbook.Spine.Count >= 2)
                                rightPage = flipView.Items.ElementAt(1) as WebView;
                            else
                                rightPage = flipView.Items.ElementAt(0) as WebView;

                            addLeftPage(rightPage);
                            ReadEpub(rightPage, idx_left);
                        }
                    }
                }
                else
                {
                    if (pre_idx < cur_idx)
                        idx_current++;
                    else
                        idx_current--;
                }

                String href = ebook.EpubEbook.Items[ebook.EpubEbook.Spine[idx_current]];
                ebook.EpubEbook.CurrentPageReading = href;

                btnBookmark.IsChecked = checkIsBookmarked(href);
                previousSelectWebView = flipView.SelectedItem as WebView;

   
            }
        }

        private WebView getLeftPage()
        {
            return flipView.Items.ElementAt(0) as WebView;
            //try
            //{
            //    return flipView.Items.ElementAt(1) as WebView;
            //}catch
            //{
            //    return flipView.Items.ElementAt(0) as WebView;
            //}
        }

        private WebView getRightPage()
        {
            return flipView.Items.ElementAt(2) as WebView;
            //try
            //{
            //    return flipView.Items.ElementAt(3) as WebView;
            //}
            //catch
            //{
            //    return flipView.Items.ElementAt(2) as WebView;
            //}
        }

        private void addLeftPage(WebView w)
        {
            flipView.Items.Remove(w);
            flipView.Items.Insert(0, w);
        }

        private void addRightPage(WebView w)
        {
            flipView.Items.Remove(w);
            flipView.Items.Add(w);
        }

        private bool checkIsBookmarked(String href)
        {
            foreach (ItemTableContent item in ebook.EpubEbook.TableContents)
            {
                if (href == item.Href)
                    return item.IsBookmark;
            }
            return false;
        }

        private void btnBookmarkList_Click(object sender, RoutedEventArgs e)
        {
            if (!popupTableContent.IsOpen)
            {
                /* The UI guidelines for a proper 'Settings' flyout are such that it should fill the height of the 
                current Window and be either narrow (346px) or wide (646px)
                Using the measurements of the Window.Curent.Bounds will help you position correctly.
                This sample here shows a simple *example* of this using the Width to get the HorizontalOffset but
                the app developer will have to perform these measurements depending on the structure of the app's 
                views in their code */

                addBookmark();

                //RootPopupBorder.Width = 270;
                popupTableContent.HorizontalOffset = Window.Current.Bounds.Width - 270 - 10;

                RootPopupBorder.Height = 500;
                popupTableContent.VerticalOffset = 170;

                popupTableContent.IsOpen = true;

            }
        }

        private void btnBookmark_Click(object sender, RoutedEventArgs e)
        {
            ItemTableContent item = findItemByLink(ebook.EpubEbook.Items[ ebook.EpubEbook.Spine[idx_current]]);

            if (item != null)
            {
                if (item.IsBookmark == true)
                {
                    item.IsBookmark = false;
                    
                    btnBookmark.IsChecked = false;
                }
                else
                {
                    item.IsBookmark = true;
                    btnBookmark.IsChecked = true;
                }
            }
        }

        




        private void btnTableContent_Click(object sender, RoutedEventArgs e)
        {
            if (!popupTableContent.IsOpen)
            {
                /* The UI guidelines for a proper 'Settings' flyout are such that it should fill the height of the 
                current Window and be either narrow (346px) or wide (646px)
                Using the measurements of the Window.Curent.Bounds will help you position correctly.
                This sample here shows a simple *example* of this using the Width to get the HorizontalOffset but
                the app developer will have to perform these measurements depending on the structure of the app's 
                views in their code */

                addTableContent();

                //RootPopupBorder.Width = 270;
                popupTableContent.HorizontalOffset = Window.Current.Bounds.Width - 270 - 10;

                RootPopupBorder.Height = 500;
                popupTableContent.VerticalOffset = 170;

                popupTableContent.IsOpen = true;
                
            }
        }

        private void ltv_tableContent_ItemClick(object sender, ItemClickEventArgs e)
        {
            popupTableContent.IsOpen = false;
            bottomAppBar.IsOpen = false;

            String href;
            if (e.ClickedItem.GetType() == typeof(uc_itemTableContent))
            {
                uc_itemTableContent item = e.ClickedItem as uc_itemTableContent;
                href = item.Item.Href;   
            
                btnBookmark.IsChecked = item.Item.IsBookmark;
            }
            else 
            {
                SmallItemTableContent item = e.ClickedItem as SmallItemTableContent;
                href = item.Item.Href;  

                btnBookmark.IsChecked = item.Item.IsBookmark;
            }

            //save current page readding
            ebook.EpubEbook.CurrentPageReading = href;

            jumpToPage(href);
            
        }

        private void jumpToPage(String href)
        {
            foreach (String hrefSpine in ebook.EpubEbook.Spine)
            {
                String path = ebook.EpubEbook.Items[hrefSpine];
                if (path == href)
                {
                    int index = ebook.EpubEbook.Spine.IndexOf(hrefSpine);
                    if (index != idx_current)
                    {
                        idx_current = index;
                        WebView cur_web = flipView.SelectedItem as WebView;

                        if (index == 0) // left page is current page
                        {
                            idx_left = 0;
                            idx_right = 1;

                            ReadEpub(cur_web, idx_current);

                            if (page1 != cur_web)
                            {
                                addRightPage(page1);

                                if (ebook.EpubEbook.Spine.Count > idx_right)
                                {
                                    ReadEpub(page1, idx_right);
                                    idx_right++;
                                }
                            }
                            if (page2 != cur_web)
                            {
                                addRightPage(page2);

                                if (ebook.EpubEbook.Spine.Count > idx_right)
                                {
                                    ReadEpub(page2, idx_right);
                                    idx_right++;
                                }

                            }
                            if (page3 != cur_web)
                            {
                                addRightPage(page3);

                                if (ebook.EpubEbook.Spine.Count > idx_right)
                                {
                                    ReadEpub(page3, idx_right);
                                    idx_right++;
                                }
                            }
                        }
                        else if (index < ebook.EpubEbook.Spine.Count - 1) // mid page is current page
                        {
                            idx_left = index - 1;
                            idx_right = index + 1;

                            ReadEpub(cur_web, idx_current);

                            bool isAlreadyAddLeft = false;

                            //add left page
                            if (page1 != cur_web)
                            {
                                addLeftPage(page1);
                                ReadEpub(page1, idx_left);

                                isAlreadyAddLeft = true;
                            }

                            //if already add left, page 2 or page 3 wiill be current page
                            if (isAlreadyAddLeft)
                            {
                                // add right page
                                if (page2 != cur_web) // page 3 will be current page
                                {
                                    addRightPage(page2);

                                    if (ebook.EpubEbook.Spine.Count > idx_right)
                                        ReadEpub(page2, idx_right);

                                }
                                else // page 2 will be current page
                                {
                                    addRightPage(page3);

                                    if (ebook.EpubEbook.Spine.Count > idx_right)
                                        ReadEpub(page3, idx_right);

                                }
                            }
                            else // page 1 is current page
                            {
                                //add left page
                                addLeftPage(page2);
                                ReadEpub(page2, idx_left);

                                //add right page
                                addRightPage(page3);

                                if (ebook.EpubEbook.Spine.Count > idx_right)
                                {
                                    ReadEpub(page3, idx_right);
                                    idx_right++;
                                }
                            }
                        }
                        else if (index == ebook.EpubEbook.Spine.Count - 1) // right page is current page
                        {
                            idx_right = index;
                            idx_left = idx_right;
                            ReadEpub(cur_web, idx_current);

                            if (page1 != cur_web)
                            {
                                addLeftPage(page1);


                                if (idx_left > 0)
                                {
                                    idx_left--;
                                    ReadEpub(page1, idx_left);
                                }
                            }
                            if (page2 != cur_web)
                            {
                                addLeftPage(page2);

                                if (idx_left > 0)
                                {
                                    idx_left--;
                                    ReadEpub(page2, idx_left);
                                }

                            }
                            if (page3 != cur_web)
                            {
                                addLeftPage(page3);

                                if (idx_left > 0)
                                {
                                    idx_left--;
                                    ReadEpub(page3, idx_left);
                                }
                            }
                        }
                        else
                        {
                            //error
                            App.ShowMessage("Error! jump to page error");
                        }
                    }
                    break;
                }
            }
        }

        

        private void AppBar_Opened(object sender, object e)
        {
            WebView webView = flipView.SelectedItem as WebView;
            SwitchWebView(webView, webViewBrushRect, false);
        }

        private void AppBar_Closed(object sender, object e)
        {
            WebView webView = flipView.SelectedItem as WebView;
            SwitchWebView(webView, webViewBrushRect, true);
        }

        private void flipView_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            Debug.WriteLine("flipView_PointerPressed");
            foreach (WebView w in flipView.Items)
            {
                if (w != flipView.SelectedItem)
                {
                    w.Opacity = 0;
                }
            }
        }

        private void flipView_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            
            Debug.WriteLine("flipView_PointerReleased");
        }

        private void flipView_DragEnter(object sender, DragEventArgs e)
        {
            Debug.WriteLine("flipView_DragEnter");
            foreach (WebView w in flipView.Items)
            {            
                 w.Opacity = 1;
                
            }
        }

        private void flipView_DragLeave(object sender, DragEventArgs e)
        {
            Debug.WriteLine("flipView_DragLeave");
        }

        private void flipView_DragOver(object sender, DragEventArgs e)
        {
            Debug.WriteLine("flipView_DragOver");
        }

        private void flipView_PointerMoved(object sender, PointerRoutedEventArgs e)
        {
            Debug.WriteLine("flipView_PointerMoved");
        }

        /***********************************/
        private void webView_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            Debug.WriteLine("webView_PointerPressed");
            foreach (WebView w in flipView.Items)
            {
                if (w != sender)
                {
                    w.Opacity = 0;
                }
            }
        }

        private void webView_DragEnter(object sender, DragEventArgs e)
        {
            Debug.WriteLine("webView_DragEnter");
            foreach (WebView w in flipView.Items)
            {
                w.Opacity = 1;

            }
        }

        private void webView_Tapped(object sender, TappedRoutedEventArgs e)
        {
            Debug.WriteLine("webView_PointerPressed");
            foreach (WebView w in flipView.Items)
            {
                if (w != sender)
                {
                    w.Opacity = 0;
                }
            }
        }

        private void pageRoot_Unloaded(object sender, RoutedEventArgs e)
        {
            EpubViewModel.CreateJsonEbook(ebook.EpubEbook);

            //reset current ebook
            App.EbookReading = null;
        }

        private void popupTableContent_Closed(object sender, object e)
        {
            ltv_tableContent.Items.Clear();
        }
        
    }
}
